package uk.ac.jisc.depositmo.widgets;

/**
 * Copyright (c) 2011, University of Southampton
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * # Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer.
 * # Redistributions in binary form must reproduce the above copyright notice, 
 *     this list of conditions and the following disclaimer in the documentation 
 *     and/or other materials provided with the distribution.
 * # Neither the name of the University of Southampton nor the names of its
 *     contributors may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 *  
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * 
 * @author Mark Borkum <mark.borkum@gmail.com>
 *
 */
public abstract class DepositForm extends Composite {
	private static final int FOREGROUND_COLOR_FOR_VALID_FIELD = SWT.COLOR_BLACK;
	
	private static final int FOREGROUND_COLOR_FOR_INVALID_FIELD = SWT.COLOR_RED;
	
	private static final String LABEL_TEXT_FOR_REQUIRED_FIELD = "*";
	
	private static final String LABEL_TEXT_FOR_OPTIONAL_FIELD = "";
	
	private static final String LABEL_TOOL_TIP_TEXT_FOR_REQUIRED_FIELD = "required";
	
	private static final String LABEL_TOOL_TIP_TEXT_FOR_OPTIONAL_FIELD = "optional";
	
	private static final String GROUP_TEXT = "SWORD Credentials";
	
	private static final boolean ENDPOINT_REQUIRED = true;
	
	private static final String ENDPOINT_LABEL_TEXT = "Service Document URL";
	
	private static final String ENDPOINT_LABEL_TOOL_TIP_TEXT = "An HTTP-URL that specifies the \"service document\" that should be used for this SWORD deposit";
	
	private static final String ENDPOINT_FIELD_MESSAGE = "http://host/path";
	
	private static final boolean USERNAME_REQUIRED = true;
	
	private static final String USERNAME_LABEL_TEXT = "Username";
	
	private static final String USERNAME_LABEL_TOOL_TIP_TEXT = "Specifies the username that should be used for this SWORD deposit";
	
	private static final String USERNAME_FIELD_MESSAGE = "";
	
	private static final boolean PASSWORD_REQUIRED = true;
	
	private static final String PASSWORD_LABEL_TEXT = "Password";
	
	private static final String PASSWORD_LABEL_TOOL_TIP_TEXT = "Specifies the password that should be used for this SWORD deposit";
	
	private static final String PASSWORD_FIELD_MESSAGE = "";
	
	public static boolean isValid(DepositForm credentialsForm) {
		return isValidEndpoint(credentialsForm.getEndpoint()) && isValidUsername(credentialsForm.getUsername()) && isValidPassword(credentialsForm.getPassword());
	}
	
	public static boolean isValidEndpoint(String string) {
		if (string.trim().equals("")) {
			return !ENDPOINT_REQUIRED;
		} else {
			try {
				URL url = new URL(string.trim());
				
				return url.getProtocol().equals("http") && !url.getHost().equals("") && !url.getPath().equals("");
			} catch (MalformedURLException e) {
				return false;
			}
		}
	}
	
	public static boolean isValidUsername(String string) {
		if (string.trim().equals("")) {
			return !USERNAME_REQUIRED;
		} else {
			return true;
		}
	}
	
	public static boolean isValidPassword(String string) {
		if (string.trim().equals("")) {
			return !PASSWORD_REQUIRED;
		} else {
			return true;
		}
	}
	
	private Group group;
	
	private Text endpointText, usernameText, passwordText;

	public DepositForm(final Composite parent) {
		super(parent, SWT.NONE);
		
		this.setLayout(new GridLayout());
		
		this.group = createGroup(this);
		
		this.endpointText = createEndpointText(this.group, createEndpointLabel(this.group));
		
		this.usernameText = createUsernameText(this.group, createUsernameLabel(this.group));
		
		this.passwordText = createPasswordText(this.group, createPasswordLabel(this.group));
	}
	
	public boolean isValid() {
		return isValid(this);
	}
	
	private Group createGroup(final Composite parent) {
		final Group group = new Group(this, SWT.NONE);
		
		final FormLayout groupLayout = new FormLayout();
		groupLayout.marginTop = 3;
		group.setLayout(groupLayout);
		
		group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		
		group.setText(GROUP_TEXT);
		
		return group;
	}
	
	private Label createEndpointLabel(final Composite parent) {
		final Label label = new Label(parent, SWT.RIGHT);
		
		label.setText(ENDPOINT_LABEL_TEXT + (ENDPOINT_REQUIRED ? LABEL_TEXT_FOR_REQUIRED_FIELD : LABEL_TEXT_FOR_OPTIONAL_FIELD));
		label.setToolTipText(ENDPOINT_LABEL_TOOL_TIP_TEXT + (ENDPOINT_REQUIRED ? " (" + LABEL_TOOL_TIP_TEXT_FOR_REQUIRED_FIELD + ")" : " (" + LABEL_TOOL_TIP_TEXT_FOR_OPTIONAL_FIELD + ")"));
		
		final FormData data = new FormData();
		data.top = new FormAttachment(0);
		data.left = new FormAttachment(0);
		data.bottom = new FormAttachment(31);
		data.right = new FormAttachment(29);
		label.setLayoutData(data);
		
		return label;
	}
	
	private Text createEndpointText(final Composite parent, final Label label) {
		final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
		
		text.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				if (isValidEndpoint(text.getText())) {
					label.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_VALID_FIELD));
					text.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_VALID_FIELD));
				} else {
					label.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_INVALID_FIELD));
					text.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_INVALID_FIELD));
				}
				
				fieldModified();
			}
		});
		
		text.setMessage(ENDPOINT_FIELD_MESSAGE);
		
		text.setText("");
		
		final FormData data = new FormData();
		data.top = new FormAttachment(0);
		data.left = new FormAttachment(31);
		data.bottom = new FormAttachment(31);
		data.right = new FormAttachment(100);
		text.setLayoutData(data);
		
		return text;
	}
	
	private Label createUsernameLabel(final Composite parent) {
		final Label label = new Label(parent, SWT.RIGHT);
		
		label.setText(USERNAME_LABEL_TEXT + (USERNAME_REQUIRED ? LABEL_TEXT_FOR_REQUIRED_FIELD : LABEL_TEXT_FOR_OPTIONAL_FIELD));
		label.setToolTipText(USERNAME_LABEL_TOOL_TIP_TEXT + (USERNAME_REQUIRED ? " (" + LABEL_TOOL_TIP_TEXT_FOR_REQUIRED_FIELD + ")" : " (" + LABEL_TOOL_TIP_TEXT_FOR_OPTIONAL_FIELD + ")"));
		
		final FormData data = new FormData();
		data.top = new FormAttachment(34);
		data.left = new FormAttachment(0);
		data.bottom = new FormAttachment(64);
		data.right = new FormAttachment(29);
		label.setLayoutData(data);
		
		return label;
	}
	
	private Text createUsernameText(final Composite parent, final Label label) {
		final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
		
		text.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				if (isValidUsername(text.getText())) {
					label.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_VALID_FIELD));
					text.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_VALID_FIELD));
				} else {
					label.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_INVALID_FIELD));
					text.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_INVALID_FIELD));
				}
				
				fieldModified();
			}
		});
		
		text.setMessage(USERNAME_FIELD_MESSAGE);
		
		text.setText("");
		
		final FormData data = new FormData();
		data.top = new FormAttachment(34);
		data.left = new FormAttachment(31);
		data.bottom = new FormAttachment(64);
		data.right = new FormAttachment(100);
		text.setLayoutData(data);
		
		return text;
	}
	
	private Label createPasswordLabel(final Composite parent) {
		final Label label = new Label(parent, SWT.RIGHT);
		
		label.setText(PASSWORD_LABEL_TEXT + (PASSWORD_REQUIRED ? LABEL_TEXT_FOR_REQUIRED_FIELD : LABEL_TEXT_FOR_OPTIONAL_FIELD));
		label.setToolTipText(PASSWORD_LABEL_TOOL_TIP_TEXT + (PASSWORD_REQUIRED ? " (" + LABEL_TOOL_TIP_TEXT_FOR_REQUIRED_FIELD + ")" : " (" + LABEL_TOOL_TIP_TEXT_FOR_OPTIONAL_FIELD + ")"));
		
		final FormData data = new FormData();
		data.top = new FormAttachment(68);
		data.left = new FormAttachment(0);
		data.bottom = new FormAttachment(100);
		data.right = new FormAttachment(29);
		label.setLayoutData(data);
		
		return label;
	}
	
	private Text createPasswordText(final Composite parent, final Label label) {
		final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
		
		text.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				if (isValidPassword(text.getText())) {
					label.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_VALID_FIELD));
					text.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_VALID_FIELD));
				} else {
					label.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_INVALID_FIELD));
					text.setForeground(getDisplay().getSystemColor(FOREGROUND_COLOR_FOR_INVALID_FIELD));
				}
				
				fieldModified();
			}
		});
		
		text.setEchoChar('*');
		
		text.setMessage(PASSWORD_FIELD_MESSAGE);
		
		text.setText("");
		
		FormData data = new FormData();
		data.top = new FormAttachment(68);
		data.left = new FormAttachment(31);
		data.bottom = new FormAttachment(100);
		data.right = new FormAttachment(100);
		text.setLayoutData(data);
		
		return text;
	}
	
	public String getEndpoint() {
		if (this.endpointText != null) {
			return this.endpointText.getText();
		} else {
			return null;
		}
	}
	
	public void setEndpoint(String string) {
		if (this.endpointText != null) {
			this.endpointText.setText(string);
		}
	}
	
	public String getUsername() {
		if (this.usernameText != null) {
			return this.usernameText.getText();
		} else {
			return null;
		}
	}
	
	public void setUsername(String string) {
		if (this.usernameText != null) {
			this.usernameText.setText(string);
		}
	}
	
	public String getPassword() {
		if (this.passwordText != null) {
			return this.passwordText.getText();
		} else {
			return null;
		}
	}
	
	public void setPassword(String string) {
		if (this.passwordText != null) {
			this.passwordText.setText(string);
		}
	}
	
	public abstract void fieldModified();
}
